/*
 * @Author: xiaosihan 
 * @Date: 2022-08-20 14:50:15 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-03-28 21:59:17
 */
import CANNON from "cannon";
import { AmbientLight, DirectionalLight, PointLight, Vector3, Clock, SphereGeometry, Mesh, MeshLambertMaterial, BoxGeometry, Quaternion } from "three";
import ThreeBase from "three-base";
import threeLoader from "three-base/threeLoader";
import threeUtils from "three-base/threeUtils";
import { degToRad } from "three/src/math/MathUtils";
import map1JPG from "./img/map1.jpg";

class CannonRenderer extends ThreeBase {

    constructor() {
        super();
    }

    // 环境光
    ambientLight = (() => {
        const ambientLight = new AmbientLight("#fff", 0.4);
        this.scene.add(ambientLight);
        return ambientLight;
    })();

    //点光源
    pointLight = (() => {
        const pointLight = new PointLight("#fff", 0.4);
        pointLight.position.set(50, 40, 50);
        this.scene.add(pointLight);
        return pointLight;
    })();

    // 方向光
    directionalLight = (() => {
        const directionalLight = new DirectionalLight("#fff", 0.4);
        directionalLight.position.set(-10, 10, 5);
        directionalLight.target.position.set(0, 0, 0);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.set(1024, 1024);
        this.scene.add(directionalLight);
        return directionalLight;
    })();

    init() {
        super.init();

        if (localStorage.lookAt && threeUtils.isDev) {
            this.resetLookAt({
                ...JSON.parse(localStorage.lookAt)
            });
        }

        if (threeUtils.isDev) {
            this.controls.addEventListener("change", () => {
                localStorage.lookAt = JSON.stringify(this.getLookAt());
            })
        }

        if (threeUtils.isProd) {
            this.resetLookAt({
                center: new Vector3(0, 0, 0),
                position: new Vector3(0, 19.951, 34.413)
            });
        }

    }

    // 物理世界
    world = (() => {
        const world = new CANNON.World();
        world.gravity = new CANNON.Vec3(0, -9.82, 0);
        return world;
    })();

    //创建一个球状刚体
    sphereBody = (() => {
        const sphereBody = new CANNON.Body({
            mass: 0.1, // kg
            position: new CANNON.Vec3(0, 12, 0), // m
            shape: new CANNON.Sphere(1),
        });

        sphereBody.material = new CANNON.Material("shpere");
        sphereBody.material.restitution = 0.5//弹力系数
        sphereBody.material.friction = 0.3//摩擦系数

        this.world.addBody(sphereBody);
        return sphereBody;
    })();

    sphereBody1 = (() => {
        const sphereBody = new CANNON.Body({
            mass: 0.1, // kg
            position: new CANNON.Vec3(0, 10, 0), // m
            shape: new CANNON.Sphere(1)
        });

        sphereBody.material = new CANNON.Material("shpere");
        sphereBody.material.restitution = 0.5//弹力系数
        sphereBody.material.friction = 0.3//摩擦系数

        this.world.addBody(sphereBody);
        return sphereBody;
    })();

    // 小球模型
    sphereMesh = (() => {
        const geo = new SphereGeometry(1, 100, 100, 0, degToRad(360), 0, degToRad(180));
        const mat = new MeshLambertMaterial({ map: threeLoader.getTexture(map1JPG) });
        const sphereMesh = new Mesh(geo, mat);
        sphereMesh.frustumCulled = false;
        //three事件
        sphereMesh.userData = { cursor: "pointer", enableEvent: true };
        sphereMesh.addEventListener("leftclick", e => {
            // this.sphereBody.position.set(0, 10, 0);
            this.sphereBody.velocity.set(0, 10, 0);
        });
        this.scene.add(sphereMesh);
        sphereMesh.onBeforeRender = () => {
            const { x: px, y: py, z: pz } = this.sphereBody.position;
            sphereMesh.position.set(px, py, pz);
            const { x, y, z, w } = this.sphereBody.quaternion;
            const qur = new Quaternion(x, y, z, w);
            sphereMesh.rotation.setFromQuaternion(qur);
        }
        return sphereMesh;
    })();

    // 小球模型
    sphereMesh1 = (() => {
        const geo = new SphereGeometry(1, 100, 100, 0, degToRad(360), 0, degToRad(180));
        const mat = new MeshLambertMaterial({ map: threeLoader.getTexture(map1JPG) });
        const sphereMesh = new Mesh(geo, mat);
        sphereMesh.frustumCulled = false;
        //three事件
        sphereMesh.userData = { cursor: "pointer", enableEvent: true };
        sphereMesh.addEventListener("leftclick", e => {
            // this.sphereBody1.position.set(0, 10, 0);
            this.sphereBody1.velocity.set(0, 10, 0);
        });
        this.scene.add(sphereMesh);
        sphereMesh.onBeforeRender = () => {
            const { x: px, y: py, z: pz } = this.sphereBody1.position;
            sphereMesh.position.set(px, py, pz);
            const { x, y, z, w } = this.sphereBody1.quaternion;
            const qur = new Quaternion(x, y, z, w);
            sphereMesh.rotation.setFromQuaternion(qur);
        }
        return sphereMesh;
    })();

    // 创建一个立方体刚体
    boxBody = (() => {
        const boxBody = new CANNON.Body({
            mass: 1, // 设置质量
            position: new CANNON.Vec3(0, 14, 0.1),
            shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1)) // 尺寸为1x1x1
        });
        this.world.addBody(boxBody);
        return boxBody;
    })();

    // 创建一个立方体模型
    // 小球模型
    boxMesh = (() => {
        const geo = new BoxGeometry(2, 2, 2);
        const mat = new MeshLambertMaterial({});
        const boxMesh = new Mesh(geo, mat);
        boxMesh.frustumCulled = false;
        //three事件
        boxMesh.userData = { cursor: "pointer", enableEvent: true };
        boxMesh.addEventListener("leftclick", e => {
            this.boxBody.position.set(0, 14, 0);
            this.boxBody.velocity.set(0, 0, 0);
        });
        this.scene.add(boxMesh);
        boxMesh.onBeforeRender = () => {
            const { x: px, y: py, z: pz } = this.boxBody.position;
            boxMesh.position.set(px, py, pz);
            const { x, y, z, w } = this.boxBody.quaternion;
            const qur = new Quaternion(x, y, z, w);
            boxMesh.rotation.setFromQuaternion(qur);
        }
        return boxMesh;
    })();



    // 地面刚体
    groundBody = (() => {
        const groundBody = new CANNON.Body({
            mass: 0,
            shape: new CANNON.Plane()
        });

        groundBody.material = new CANNON.Material("shpere");
        groundBody.material.restitution = 1//弹力系数
        groundBody.material.friction = 0.3//摩擦系数

        var q = new CANNON.Quaternion();
        q.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), degToRad(-90));
        groundBody.quaternion = q;

        this.world.addBody(groundBody);
        return groundBody;
    })();

    clock = new Clock();
    fixedTimeStep = 1.0 / 60.0; // seconds
    maxSubSteps = 3;

    render() {
        super.render();

        // var lastTime;
        // (function simloop(time) {
        //     requestAnimationFrame(simloop);
        //     if (lastTime !== undefined) {
        //         var dt = (time - lastTime) / 1000;
        //         world.step(fixedTimeStep, dt, maxSubSteps);
        //     }
        //     console.log("Sphere z position: " + sphereBody.position.z);
        //     lastTime = time;
        // })();

        this.world.step(this.fixedTimeStep, this.clock.getDelta(), this.maxSubSteps);
    }


}


const cannonRenderer = window.cannonRenderer = new CannonRenderer();

export default cannonRenderer;